package cn.tedu.aiumall.passport.service.impl;

import cn.tedu.aiumall.passport.ex.ServiceCode;
import cn.tedu.aiumall.passport.ex.ServiceException;
import cn.tedu.aiumall.passport.mapper.AdminMapper;
import cn.tedu.aiumall.passport.mapper.AdminRoleMapper;
import cn.tedu.aiumall.passport.mapper.RoleMapper;
import cn.tedu.aiumall.passport.pojo.dto.AdminAddNewDTO;
import cn.tedu.aiumall.passport.pojo.dto.AdminLoginInfoDTO;
import cn.tedu.aiumall.passport.pojo.dto.AdminUpdateDTO;
import cn.tedu.aiumall.passport.pojo.dto.AdminUpdatePasswordDTO;
import cn.tedu.aiumall.passport.pojo.entity.Admin;
import cn.tedu.aiumall.passport.pojo.entity.AdminRole;
import cn.tedu.aiumall.passport.pojo.vo.AdminListItemVO;
import cn.tedu.aiumall.passport.pojo.vo.AdminLoginInfoVO;
import cn.tedu.aiumall.passport.pojo.vo.AdminStandardVO;
import cn.tedu.aiumall.passport.security.AdminDetails;
import cn.tedu.aiumall.passport.service.IAdminService;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class AdminServiceImpl implements IAdminService {

    public static String sendMessage;
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AdminRoleMapper adminRoleMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Value("${aiumall.jwt.secret-key}")
    private String secureKey;

    @Override
    public String login(AdminLoginInfoDTO adminLoginInfoDTO) {
          log.info("开始处理登录认证的业务，参数：{}",adminLoginInfoDTO);
          String usernameOrPhoneOrEmail=adminLoginInfoDTO.getUsernameOrPhoneOrEmail();
          log.info("usernameOrPhoneOrEmail的参数为:{}",usernameOrPhoneOrEmail);
        AdminLoginInfoVO queryResult = adminMapper
                .getLoginInfoByUsernameOrPhoneOrEmail(usernameOrPhoneOrEmail);
        if (queryResult==null){
            String message="登录失败！该用户不存在！";
            log.info(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        if (queryResult.getEnable()==0){
            String message="登录失败！该用户已被禁用！";
            log.info(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }
        if (!adminLoginInfoDTO.getSendMessage().equals(sendMessage)){
            String message="登录失败！验证码不正确!";
            log.info(message);
            throw new ServiceException(ServiceCode.ERR_SENDMESSAGE,message);
        }
        String username= queryResult.getUsername();
        log.info("用户名为：{}",username);
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                username,
                adminLoginInfoDTO.getPassword()
        );
        Authentication authenticateResult = authenticationManager.authenticate(authentication);
        log.info("Spring Security已通过认证，返回的结果：{}",authenticateResult);
        log.info("返回认证信息的当事人(Principal)的类型为：{}",authenticateResult.getPrincipal().getClass().getName());
        log.info("返回认证信息的当事人(Principal)的数据为：{}",authenticateResult.getPrincipal());
        AdminDetails principal=(AdminDetails)authenticateResult.getPrincipal();
        Long id=principal.getId();
        log.info("认证信息中的id为：{}",id);
        username=principal.getUsername();
        log.info("认证信息中的用户名为：{}",username);
        Collection<GrantedAuthority> authorities=principal.getAuthorities();
        log.info("认证信息中的权限：{}",authorities);
        String authorityListString = JSON.toJSONString(authorities);
        log.info("认证信息中的权限转换为JSON字符串：{}", authorityListString);

        //准备claims的值
        Map<String,Object> claims=new HashMap<>();
        claims.put("id",id);
        claims.put("username",username);
        claims.put("authorities",authorityListString);

        //准备过期时间
        Date expiration=new Date(System.currentTimeMillis()+15 * 24 * 60 * 60 * 1000);
        log.info("过期时间:{}",expiration);

        // JWT的组成：Header（头：算法和Token类型）、Payload（载荷）、Signature（签名）
        String jwt= Jwts.builder().
                setHeaderParam("alg","HS256").
                setHeaderParam("tye","JWT").
                setClaims(claims).
                setExpiration(expiration).
                signWith(SignatureAlgorithm.HS256,secureKey).
                compact();
        log.info("JWT:{}",jwt);

        return jwt;
    }

    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        log.info("放入参数adminAddNewDTO{}",adminAddNewDTO);
        String username=adminAddNewDTO.getUsername();
        log.info("用户名称为{}",username);
        int countByUsername = adminMapper.countByUsername(username);
        if (countByUsername!=0){
            String message="添加用户失败，用户名已存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }

        String phone=adminAddNewDTO.getPhone();
        log.info("用户号码为{}",phone);
        int countByPhone = adminMapper.countByPhone(phone);
        if (countByPhone!=0){
            String message="添加用户失败，号码已存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }

        String email=adminAddNewDTO.getEmail();
        log.info("用户邮箱为{}",email);
        int countByEmail = adminMapper.countByEmail(email);
        if (countByEmail!=0){
            String message="添加用户失败，邮箱已存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }

        Admin admin=new Admin();
        BeanUtils.copyProperties(adminAddNewDTO,admin);
        String rawPassword=admin.getPassword();
        String encodedPassword=passwordEncoder.encode(rawPassword);
        admin.setPassword(encodedPassword);
        log.info("添加之前的用户信息：{}",admin);
        admin.setLoginCount(0);
        int rows=adminMapper.insert(admin);
        log.info("添加之后的用户信息：{}",admin);
        if (rows!=1){
            String message="添加用户失败，系统忙,请重新刷新页面再尝试!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }
        // 检查各角色id是否存在
        Long[] roleIds = adminAddNewDTO.getRoleIds();
        int countByIds = roleMapper.countByIds(roleIds);
        if (countByIds != roleIds.length) {
            // 是：抛出ServiceException（ERR_BAD_REQUEST）
            String message = "添加管理员失败，角色数据错误！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, message);
        }
        log.debug("准备插入管理员与角色的关联关系");
        LocalDateTime now = LocalDateTime.now();
        List<AdminRole> adminRoleList = new ArrayList<>();
        for (int i = 0; i < roleIds.length; i++) {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(admin.getId());
            adminRole.setRoleId(roleIds[i]);
            adminRole.setGmtCreate(now);
            adminRole.setGmtModified(now);
            adminRoleList.add(adminRole);
        }
        rows = adminRoleMapper.insertBatch(adminRoleList);
        if (rows != roleIds.length) {
            // 是：抛出ServiceException（ERR_INSERT）
            String message = "添加管理员失败，服务器忙，请稍后再尝试！[错误代码：2]";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        log.debug("添加管理员完成！");


    }

    @Override
    public void deleteById(Long id) {
        List<AdminListItemVO> list = adminMapper.list();
        if (list==null){
            String message="删除失败，您所删除的管理员不存在";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        int rows=adminMapper.deleteById(id);
        if (rows!=1){
            String message="删除失败，系统繁忙，请联系负责人员或刷新后重试!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_DELETE,message);
        }
        // 删除“管理员与角色”的关联数据
        rows = adminRoleMapper.deleteByAdmin(id);
        // 判断返回值是否小于1
        if (rows < 1) {
            // 抛出ServiceException，业务状态码：DELETE对应的常量
            String message = "删除管理员失败！服务器忙，请稍后再次尝试！[错误代码：2]";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }

    }

    @Override
    public void setEnable(Long id) {
        log.debug("开始处理【启用管理员账号】的业务：id={}", id);
        // 根据id查询管理员数据
        AdminStandardVO resultQuery = adminMapper.getStandardById(id);
        // 判断查询结果是否为null
        if (resultQuery == null) {
            // 是：ServiceException：NOT_FOUND
            String message = "启用管理员账号失败！尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 判断查询结果中的enable是否为1
        if (resultQuery.getEnable() == 1) {
            // 是：ServiceException：CONFLICT
            String message = "启用管理员账号失败！当前账号已经启用！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        // Admin admin = new Admin(); admin.setId(id); admin.setEnable(1);
        Admin admin = new Admin();
        admin.setId(id);
        admin.setEnable(1);
        // 执行更新，获取返回值
        int rows = adminMapper.update(admin);
        // 判断返回值是否不为1
        if (rows != 1) {
            // 是：ServiceException：UPDATE
            String message = "启用管理员账号失败！服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public void setDisable(Long id) {
        log.debug("开始处理【禁用管理员账号】的业务：id={}", id);
        // 根据id查询管理员数据
        AdminStandardVO resultQuery = adminMapper.getStandardById(id);
        // 判断查询结果是否为null
        if (resultQuery == null) {
            // 是：ServiceException：NOT_FOUND
            String message = "禁用管理员账号失败！尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 判断查询结果中的enable是否为0
        if (resultQuery.getEnable() == 0) {
            // 是：ServiceException：CONFLICT
            String message = "禁用管理员账号失败！当前账号已经禁用！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        // Admin admin = new Admin(); admin.setId(id); admin.setEnable(1);
        Admin admin = new Admin();
        admin.setId(id);
        admin.setEnable(0);
        // 执行更新，获取返回值
        int rows = adminMapper.update(admin);
        // 判断返回值是否不为1
        if (rows != 1) {
            // 是：ServiceException：UPDATE
            String message = "禁用管理员账号失败！服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public void updatePassword(AdminUpdatePasswordDTO adminUpdatePasswordDTO) {
        log.info("",adminUpdatePasswordDTO);
        String username=adminUpdatePasswordDTO.getUsername();
        log.info("开始处理【修改管理员密码】的业务：username={}",username);
        AdminLoginInfoVO queryResult = adminMapper.getLoginInfoByUsername(username);
        String oldPassword=adminUpdatePasswordDTO.getOldPassword();
        String newPassword=adminUpdatePasswordDTO.getNewPassword();
        BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
        boolean matches = passwordEncoder.matches(oldPassword, queryResult.getPassword());
        if (queryResult==null){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"更改管理员密码错误，该用户不存在!");
        }
        if (matches==false){
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"原密码不正确!");
        }
        Long id= queryResult.getId();
        if (id == 1) {
            // 抛出ServiceException，业务状态码：40400
            String message = "修改管理员密码失败！不能修改最高管理员密码!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        if (queryResult.getEnable()==0){
            String message="修改失败，该管理员账户已禁用！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE,message);
        }
        Admin admin=new Admin();
        admin.setId(id);
        String encodedPassword=passwordEncoder.encode(newPassword);
        admin.setPassword(encodedPassword);
        int rows=adminMapper.update(admin);
        log.info("修改密码成功!");
        if (rows!=1){
            String message="修改失败，系统忙，请联系负责人员或者重新刷新页面";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE,message);
        }
    }

    @Override
    public void updateAdminInfo(Long id, AdminUpdateDTO adminUpdateDTO) {
        log.info("开始处理【修改管理员密码】的业务：id={}",id);
        AdminStandardVO standardById = adminMapper.getStandardById(id);
        if (standardById==null){
            String message="修改失败，需要修改密码的管理员账户不存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        if (standardById.getEnable()==0){
            String message="修改失败，该管理员账户已禁用！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE,message);
        }
        Admin admin=new Admin();
        BeanUtils.copyProperties(adminUpdateDTO,admin);
        admin.setId(id);
        int rows=adminMapper.update(admin);
        if (rows!=1){
            String message="修改失败，系统忙，请联系负责人员或者重新刷新页面";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE,message);
        }
    }

    @Override
    public List<AdminListItemVO> list() {
        log.info("开始处理【查询管理员列表】的业务……");
        return adminMapper.list();
    }


}
